package com.xhwl.logistics.strategy.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.xhwl.logistics.bo.VehicleAccessRecordSecondBO;
import com.xhwl.logistics.bo.VehicleCarRecordInParkingLotBO;
import com.xhwl.logistics.bo.VehicleCarportBO;
import com.xhwl.logistics.bo.cent.DeviceBO;
import com.xhwl.logistics.bo.cent.VehicleIntegratedConfigBO;
import com.xhwl.logistics.bo.cent.VehicleSystemInfoBO;
import com.xhwl.logistics.bo.input.QueryVehicleAccessRecordRealtimeBO;
import com.xhwl.logistics.bo.input.QueryVehicleCarRecordInParkingLotBO;
import com.xhwl.logistics.bo.input.QueryVehicleCarportBO;
import com.xhwl.logistics.bo.manipulate.VehicleSyncBO;
import com.xhwl.logistics.constant.VehicleConstant;
import com.xhwl.logistics.converter.mapstruct.*;
import com.xhwl.logistics.dao.mapper.IVehicleParkingLotInfoMapper;
import com.xhwl.logistics.dao.mapper.IVehicleParkingLotMapper;
import com.xhwl.logistics.dto.http.CarportCoSonDTO;
import com.xhwl.logistics.dto.http.DeviceInfoCoSonDTO;
import com.xhwl.logistics.dto.http.ParkingLotInfoCoSonDTO;
import com.xhwl.logistics.dto.http.query.QueryCommonCoSonDTO;
import com.xhwl.logistics.entity.VehicleParkingLot;
import com.xhwl.logistics.po.VehicleParkingLotInfoPO;
import com.xhwl.logistics.po.VehicleParkingLotPO;
import com.xhwl.logistics.service.IVehicleAccessRecordService;
import com.xhwl.logistics.service.IVehiclePayRecordService;
import com.xhwl.logistics.service.business.VehicleDeviceDataPushBusinessService;
import com.xhwl.logistics.service.cent.IBIVehicleService;
import com.xhwl.logistics.service.cent.QueryDeviceSecondService;
import com.xhwl.logistics.service.impl.VehicleParkingLotServiceImpl;
import com.xhwl.logistics.service.impl.http.CoSonHttpServiceImpl;
import com.xhwl.logistics.strategy.IVehicleParkingLotHandler;
import com.xhwl.logistics.util.AboutDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.util.Optionals;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
//@Service
public class VehicleParkingLotCoSonHandlerImpl implements IVehicleParkingLotHandler {

    @Autowired
    private CoSonHttpServiceImpl coSonHttpService;

    @Autowired
    private VehicleParkingLotServiceImpl vehicleParkingLotService;

    @Autowired
    private IVehicleParkingLotInfoMapper vehicleParkingLotInfoMapper;

    @Autowired
    private VehicleAccessRecordConverter vehicleAccessRecordConverter;

    @Autowired
    private VehiclePayRecordConverter vehiclePayRecordConverter;

    @Autowired
    private VehicleCarportConverter vehicleCarportConverter;

    @Autowired
    private VehicleSyncConverter vehicleSyncConverter;

    @Autowired
    private QueryDeviceSecondService queryDeviceSecondService;

    @Autowired
    private CentDeviceConverter centDeviceConverter;

    @Autowired
    private VehicleDeviceDataPushBusinessService vehicleDeviceDataPushBusinessService;

    @Autowired
    private IVehicleAccessRecordService vehicleAccessRecordService;

    @Autowired
    private IVehiclePayRecordService vehiclePayRecordService;

    @Autowired
    private IBIVehicleService biVehicleService;

    @Autowired
    private CentBiConverter centBiConverter;

    @Autowired
    private IVehicleParkingLotMapper vehicleParkingLotMapper;

    @Override
    public void sync(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, VehicleSyncBO vehicleSyncBO) {
        log.info("Co Son Sync!");
        log.info("vehicleIntegratedConfigBO: " + vehicleIntegratedConfigBO);
        Integer projectId = vehicleIntegratedConfigBO.getVehicleSystemInfoBO().getProjectId();

        Optional<VehicleParkingLotInfoPO> optionalVehicleParkingLotInfoPO = vehicleParkingLotInfoMapper.queryParkingLotInfoByProjectId(projectId);

        Optional<VehicleParkingLotPO> optionalVehicleParkingLotPO;
        if (optionalVehicleParkingLotInfoPO.isPresent()) {
            VehicleParkingLotInfoPO vehicleParkingLotInfoPO = optionalVehicleParkingLotInfoPO.get();
            List<VehicleParkingLotPO> vehicleParkingLotPOList = vehicleParkingLotInfoPO.getVehicleParkingLotPOList();
            Assert.isTrue(vehicleParkingLotPOList.size() == 1, "项目下，对于科松厂商的车场只能有一个");

            VehicleParkingLotPO vehicleParkingLotPO = vehicleParkingLotPOList.get(0);
            optionalVehicleParkingLotPO = Optional.of(vehicleParkingLotPO);
        } else {
            optionalVehicleParkingLotPO = Optional.empty();
        }
        ParkingLotInfoCoSonDTO parkingLotInfoCoSonDTO = coSonHttpService.queryParkingLotInfo(vehicleIntegratedConfigBO, new QueryCommonCoSonDTO());
        VehicleParkingLot tempForVehicleParkingLot = new VehicleParkingLot();
        Optionals.ifPresentOrElse(
                optionalVehicleParkingLotPO,
                vehicleParkingLotPO -> {
                    tempForVehicleParkingLot.setId(vehicleParkingLotPO.getId());
                    tempForVehicleParkingLot.setParkId(vehicleParkingLotPO.getParkId());

                    VehicleParkingLot vehicleParkingLot = vehicleSyncConverter.toVehicleParkingLotUpdateForCoSon(parkingLotInfoCoSonDTO, vehicleParkingLotPO.getId());
                    vehicleParkingLotService.updateById(vehicleParkingLot);
                },
                () -> {
                    VehicleParkingLot vehicleParkingLot = vehicleSyncConverter.toVehicleParkingLotAddForCoSon(parkingLotInfoCoSonDTO, projectId);
                    vehicleParkingLotService.save(vehicleParkingLot);

                    tempForVehicleParkingLot.setId(vehicleParkingLot.getId());
                    tempForVehicleParkingLot.setParkId(vehicleParkingLot.getParkId());
                }
        );
        log.info("CoSon sync end!");

    }
    @Override
    public VehicleCarportBO queryCarport(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, QueryVehicleCarportBO queryVehicleCarportBO) {

        CarportCoSonDTO carportCoSonDTO = coSonHttpService.queryCarport(vehicleIntegratedConfigBO,new QueryCommonCoSonDTO());
        return vehicleCarportConverter.carportCoSonDTO2VehicleCarportBO(carportCoSonDTO);

    }

    @Override
    public void syncDevice(VehicleIntegratedConfigBO vehicleIntegratedConfigBO) {
        log.info("CoSon sync device start!");
        log.info("vehicleIntegratedConfigBO: " + vehicleIntegratedConfigBO);

        VehicleSystemInfoBO vehicleSystemInfoBO = vehicleIntegratedConfigBO.getVehicleSystemInfoBO();
        Integer projectId = vehicleSystemInfoBO.getProjectId();
        Integer productId = vehicleSystemInfoBO.getProductId();
        Integer productCategoryId = vehicleSystemInfoBO.getProductCategoryId();

        List<DeviceInfoCoSonDTO> deviceInfoCoSonDTOList = coSonHttpService.queryDeviceInfo(vehicleIntegratedConfigBO,new QueryCommonCoSonDTO());
        List<DeviceBO> deviceListFromCentDevice = queryDeviceSecondService.queryDevicesByProjectId(projectId);
        Map<String, Integer> temp = deviceListFromCentDevice.stream().collect(Collectors.toMap(DeviceBO::getNumber, DeviceBO::getId));
        List<DeviceBO> add = new ArrayList<>();
        List<DeviceBO> update = new ArrayList<>();
        deviceInfoCoSonDTOList.forEach(deviceInfoCoSonDTO -> {
            Optionals.ifPresentOrElse(
                    Optional.ofNullable(temp.get(deviceInfoCoSonDTO.getVehNumber())),
                    id -> {
                        DeviceBO deviceBO = centDeviceConverter.toDeviceBOByCoSon(id, deviceInfoCoSonDTO, projectId, productId, productCategoryId);
                          if(null != deviceInfoCoSonDTO.getVehStatus()){
                            try {
                                vehicleDeviceDataPushBusinessService.coSonDeviceStatus(deviceInfoCoSonDTO, projectId);
                            } catch (Exception exception) {
                                throw exception;
                            }
                        }
                        update.add(deviceBO);
                    },
                    () -> {
                        DeviceBO deviceBO = centDeviceConverter.toDeviceBOByCoSon(deviceInfoCoSonDTO, projectId, productId, productCategoryId);
                        add.add(deviceBO);
                    });
        });

        if (!add.isEmpty()) {
            queryDeviceSecondService.addDevices(add);
        }

        if (!update.isEmpty()) {
            queryDeviceSecondService.updateDevices(update);
        }

        log.info("CoSon sync device end!");
    }


    @Override
    public VehicleCarRecordInParkingLotBO queryCarRecordInParkingLot(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, QueryVehicleCarRecordInParkingLotBO queryVehicleCarRecordInParkingLotBO) {
        return IVehicleParkingLotHandler.super.queryCarRecordInParkingLot(vehicleIntegratedConfigBO, queryVehicleCarRecordInParkingLotBO);
    }

    @Override
    public List<VehicleAccessRecordSecondBO> queryAccessRecordRealtime(VehicleIntegratedConfigBO vehicleIntegratedConfigBO, QueryVehicleAccessRecordRealtimeBO queryVehicleAccessRecordRealtimeBO) {
        return IVehicleParkingLotHandler.super.queryAccessRecordRealtime(vehicleIntegratedConfigBO, queryVehicleAccessRecordRealtimeBO);
    }

    //@Async("threadPoolTaskExecutorForSchedule")
    @Override
    public void statisticsToBi(VehicleIntegratedConfigBO vehicleIntegratedConfigBO) {
        log.info("车行数据汇总bi开启");
        try {
            Integer projectId = vehicleIntegratedConfigBO.getVehicleSystemInfoBO().getProjectId();

            VehicleParkingLot vehicleParkingLot = vehicleParkingLotMapper.selectOne(new LambdaQueryWrapper<VehicleParkingLot>().eq(VehicleParkingLot::getProjectId, projectId));
            String parkingLotName = vehicleParkingLot.getParkingLotName();
            String parkId = vehicleParkingLot.getParkId();

            Date processDate = new Date();
            Date ingestionDate = AboutDateUtil.dateMinusHour(AboutDateUtil.theSameDayHourOfDate(processDate, VehicleConstant.vehicleTimeZone), 1);
            Integer enterForCount = vehicleAccessRecordService.accessRecordForCount(vehicleAccessRecordConverter.toQueryVehicleAccessRecordForCountBOForEnter(projectId, parkId, ingestionDate));
            Integer goOutForCount = vehicleAccessRecordService.accessRecordForCount(vehicleAccessRecordConverter.toQueryVehicleAccessRecordForCountBOForGoOut(projectId, parkId, ingestionDate));
            Integer totalForCount = enterForCount + goOutForCount;
            biVehicleService.addDwsAccessRecordForHour(centBiConverter.toCreateBiVehicleAccessRecordHourFeignDTO(projectId, parkingLotName, totalForCount, enterForCount, goOutForCount, processDate, ingestionDate));

            Integer payTotalForSum = vehiclePayRecordService.payRecordForCount(vehiclePayRecordConverter.toQueryVehiclePayRecordForCountBO(projectId, parkId, ingestionDate));
            biVehicleService.addDwsPayRecordForHour(centBiConverter.toCreateBiVehiclePayRecordHourFeignDTO(projectId, parkingLotName, payTotalForSum, 0, 0, 0, 0, processDate, ingestionDate));
        } catch (Exception e) {
            log.error("科松车场定时汇总数据到BI发生异常！异常原因：" + e.getMessage() + "所发生的的汇总错误的项目id：" + vehicleIntegratedConfigBO.getVehicleSystemInfoBO().getProjectId());
        }
    }

}
